package com.njtech.pet.controller;

import com.alibaba.fastjson.JSON;
import com.google.gson.Gson;
import com.njtech.pet.constant.Constant;
import com.njtech.pet.entity.*;
import com.njtech.pet.service.*;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.lang.reflect.InvocationTargetException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author ：Hana
 * @date ：Created in 2020/3/10 11:22
 * @description：
 * @modified By：
 * @version: $
 */
@Controller
@RequestMapping("/bill")
public class BillController {
    @Autowired
    private BillService billService;

    @Autowired
    private CreditService creditService;

    @Autowired
    private ItemService itemService;

    @Autowired
    private PersonService personService;

    @Autowired
    private PetService petService;

    @Autowired
    private MemberService memberService;

    @Autowired
    private UserService userService;

    /***********************************************************************用户功能*****************************************************************/


    /**
     * @return 商品首页
     */
    @RequestMapping("index")
    public String index() {
        return "billIndex";
    }


    /**
     * 用户功能0：计算订单总价
     * 在订单页根据优惠券及会员等级计算商品最终价格并返回
     * @param req
     * @return
     */
    @RequestMapping("/calPrice")
    @ResponseBody
    public String calPrice(HttpServletRequest req){
        User user = new User();
        Item item = new Item();
        Map<String,String> map = new HashMap<>();

        System.out.print("uid = " + req.getParameter("uid") + "\n itemId = " + req.getParameter("itemId") + "\n couponId = " + req.getParameter("couponId"));

        //设置用户id
        if (req.getParameter("uid") != null) {
            user = userService.selectByUserId(Integer.parseInt(req.getParameter("uid")));
        } else {
            map.put("msg", "用户id不允许为空");
        }

        //设置订单积分
        if (req.getParameter("itemId") != null) {
            item = itemService.selectById(Integer.parseInt(req.getParameter("itemId")));
        } else {
            map.put("msg", "商品id不允许为空");
        }

        //使用优惠券，计算订单最终价格
        Double finalPrice;
        Item coupon;
        if(req.getParameter("couponId") != null){
            coupon = itemService.selectById(Integer.parseInt(req.getParameter("couponId")));
            finalPrice = memberService.priceDiscount(item,user,coupon);
        }else{
            finalPrice = memberService.priceDiscount(item,user,null);
        }
        map.put("price",finalPrice.toString());
        return JSON.toJSONString(map);
    }


    /**
     * 用户功能1：生成订单
     * 需要更新数据库中price字段，为订单总价
     * @param req
     * @return 返回生成订单的billId
     * @throws InvocationTargetException
     * @throws IllegalAccessException
     */
    @RequestMapping("/insert")
    @ResponseBody
    public String insert(HttpServletRequest req) throws InvocationTargetException, IllegalAccessException {
        Bill bill = new Bill();
        Map<String,String> map = new HashMap<>();
        BeanUtils.populate(bill, req.getParameterMap());
        User user = new User();
        Person buyer = new Person(), insurer = new Person();
        Pet pet = new Pet();
        bill.setType("商品结算");

        //设置用户id
        if (req.getParameter("uid") != null) {
            user = userService.selectByUserId(Integer.parseInt(req.getParameter("uid")));
            bill.setUser(user);
        } else {
            map.put("msg", "用户id不允许为空");
        }

        //设置订单最终价格
        if (req.getParameter("itemId") != null) {
            Item item = itemService.selectById(Integer.parseInt(req.getParameter("itemId")));
            bill.setItem(item);
            Double finalPrice;
            if(req.getParameter("couponId") != null){
                Item coupon = itemService.selectById(Integer.parseInt(req.getParameter("couponId")));
                finalPrice = memberService.priceDiscount(item,user,coupon);
            }else{
                finalPrice = memberService.priceDiscount(item,user,null);
            }
            BeanUtils.setProperty(bill,"credit",item.getCredit());
            BeanUtils.setProperty(bill,"price",finalPrice);
        } else {
            map.put("msg", "商品id不允许为空");
        }

        //设置投保人id
        if (req.getParameter("buyerId") != null) {
            Integer buyerId = Integer.parseInt(req.getParameter("insuredId"));
            System.out.print("\n投保人id：" + buyerId + "\n");
            Person testBuyer = personService.selectByPersonId(buyerId);
            System.out.print(testBuyer);
            buyer.setId(buyerId);
            bill.setBuyer(buyer);
        } else {
            map.put("msg", "投保人id不允许为空");
        }

        //设置被保人id
        if (req.getParameter("insuredId") != null) {
            Integer insuredId = Integer.parseInt(req.getParameter("insuredId"));
            System.out.print("\n受保人id：" + insuredId + "\n");
            Person testPer = personService.selectByPersonId(insuredId);
            System.out.print(testPer);
            insurer.setId(insuredId);
            bill.setInsured(insurer);
        } else {
            map.put("msg", "被保险人id不允许为空");
        }

        //设置被保宠物id
        if (req.getParameter("petId") != null) {
            System.out.print("\n受保宠物id：" + req.getParameter("petId") + "\n");
            Pet testPet = petService.selectByPetId((Integer.parseInt(req.getParameter("petId"))));
            System.out.print(testPet);
            pet.setId(Integer.parseInt(req.getParameter("petId")));
            bill.setPet(pet);
        } else {
            map.put("msg", "被保险宠物不允许为空");
        }

        //生成订单时默认状态是"订单未支付"
        bill.setState(Constant.Bill.STATE_BILL_UNPAID.getValue());

        //生成订单
        Integer num = billService.insert(bill);
        System.out.print("插入记录条数：" + num + "\n");

        //查询该用户最新的订单，返回billId
        List bills = billService.selectByUser(user,null,null,null,null);
        Bill latest_bill = (Bill)bills.get(0);
        map.put("billId",latest_bill.getId().toString());
        return JSON.toJSONString(map);
    }


    /**
     * 用户功能2：修改订单
     * 订单状态为“订单未支付“时允许用户修改被保人insuredId和被保宠物petId
     *
     * @param req
     * @return
     * @throws InvocationTargetException
     * @throws IllegalAccessException
     */
    @RequestMapping("/updateByUser")
    @ResponseBody
    public String updateByUser(HttpServletRequest req) throws InvocationTargetException, IllegalAccessException {
        Bill bill = new Bill();
        Map<String, String> map = new HashMap<>();
        BeanUtils.populate(bill, req.getParameterMap());
        Person insurer = new Person();
        Pet pet = new Pet();
        if (req.getParameter("insuredId") != null) {
            insurer.setId(Integer.parseInt(req.getParameter("insuredId")));
            bill.setInsured(insurer);
        } else {
            map.put("msg", "被保险人id不允许为空");
        }
        if (req.getParameter("petId") != null) {
            pet.setId(Integer.parseInt(req.getParameter("petId")));
            bill.setPet(pet);
        } else {
            map.put("msg", "被保险宠物不允许为空");
        }
        Integer num = billService.updateByBillId(bill);
        if(num != 0){
            map.put("msg", "订单修改成功");
        }else{
            map.put("msg", "订单修改失败");
        }
        return JSON.toJSONString(map);
    }

    /**
     * 用户功能3：取消订单
     * 订单状态为“订单未支付”时允许用户取消，首先判断此操作合法性，然后进行订单状态更新
     * @param req
     * @return
     */
    @RequestMapping("/delete")
    @ResponseBody
    public String delete(HttpServletRequest req) {
        Bill delete_bill = new Bill();
        Integer num = 0;
        Map<String, String> map = new HashMap<>();

        //判断用户订单合法性
        HttpSession session = req.getSession();
        int uid = Integer.parseInt((String) session.getAttribute("uid"));
        String billId = req.getParameter("billId");
        if(billId != null) {
            Integer id = Integer.parseInt(billId);
            Bill bill = billService.selectByBillId(id);
            if(bill.getUser().getId() != uid){
                map.put("msg", "用户id与此订单中信息不一致，用户无法取消订单");
            }else {
                delete_bill.setId(id);
                delete_bill.setState(Constant.Bill.STATE_BILL_DELETE.getValue());
                num = billService.updateByBillId(delete_bill);
                if(num != 0){
                    map.put("msg", "订单取消成功");
                }
            }
        }else{
            map.put("msg","无效的订单编号");
        }
        return JSON.toJSONString(map);
    }


    /**
     * 用户功能4：查找订单
     * 查询条件为用户id,订单状态,订单类型,起始日期
     * Integer uid, billState, billType, beginDate, endDate
     * @param req
     * @return
     * @RequestParam
     */
    @RequestMapping("/searchByUser")
    @ResponseBody
    public String searchByUser(HttpServletRequest req) {
        Map<String,List> map = new HashMap<>();
        List object;
        User user = new User();
        if(req.getParameter("uid") != null){
            user.setId(Integer.parseInt(req.getParameter("uid")));
        }else{
            Map<String,String> newMap = new HashMap<>();
            newMap.put("msg","用户id为空无法查询");
            return JSON.toJSONString(newMap);
        }
        object = billService.selectByUser(user,req.getParameter("billState"),req.getParameter("billType"), req.getParameter("beginDate"), req.getParameter("endDate"));
        map.put("bills", object);
//        Gson gson = new Gson();
//        return gson.toJson(map);
        return JSON.toJSONString(map);
    }


    /**
     * 用户功能5：根据订单id查找订单
     *
     * @param billId
     * @return
     */
    @RequestMapping("/selectByBillId")
    @ResponseBody
    public String selectByBillId(Integer billId) {
        Bill bill = billService.selectByBillId(billId);
        Map<String, Object> map = new HashMap<>();
        if (bill != null) {
            map.put("msg", bill);
        } else {
            map.put("msg", "查找的订单不存在");
        }
        Gson gson = new Gson();
        return gson.toJson(map);
    }


    /**
     * 用户功能6：订单支付
     * 修改whenEffect useDate expireDate credit state
     * @param billId
     * @param uid
     * @return
     */
    @RequestMapping("/pay")
    @ResponseBody
    public String billPay(Integer billId,Integer uid) {
        Bill bill = new Bill();
        Bill newBill;
        Map<String, String> map = new HashMap<>();

        if (billService.selectByBillId(billId).getState().equals(Constant.Bill.STATE_BILL_UNPAID.getValue())) {
            //状态更新为"订单已支付"
            bill.setId(billId);
            bill.setState(Constant.Bill.STATE_BILL_PAID.getValue());

            //更新支付方式和凭证
            bill.setBuyWay("测试支付");
            bill.setProof("测试凭证");
            billService.updateByBillId(bill);
            newBill = billService.selectByBillId(billId);
            Bill billDate = new Bill();
            billDate.setId(billId);

            //增加用户积分
            User user = new User();
            user.setId(uid);
            creditService.addCredit(newBill,user);

            //更新两个日期:有效日期 失效日期
            Date createDate = newBill.getUpdateDate();
            System.out.print("\n" + createDate + "\n");

            Calendar calendar = new GregorianCalendar();
            calendar.setTime(createDate);
            calendar.add(Calendar.DATE,1); //把日期往后增加一天,整数  往后推,负数往前移动
            Date useDate = calendar.getTime(); //这个时间就是日期往后推一天的结果
            System.out.print(createDate + "  " + useDate);
            billDate.setUseDate(useDate);
            Integer last = newBill.getItem().getHowLong();
            calendar.setTime(useDate);
            calendar.add(Calendar.DATE,last);
            Date expireDate = calendar.getTime();
            billDate.setExpireDate(expireDate);
            Integer num = billService.updateByBillId(billDate);
            map.put("msg",num.toString() + "个订单已完成支付");
        }else{
            map.put("msg","订单已完成,请勿再次支付");
        }
        return JSON.toJSONString(map);
    }


    /**
     * 用户功能7：订单退款
     * 修改相关信息
     *
     * @param billId
     * @param uid
     * @return
     */
    @RequestMapping("/refund")
    @ResponseBody
    public String refundByUser(Integer billId,Integer uid) {
        Map<String, String> map = new HashMap<>();
        Bill bill = new Bill();

        //金额退还未完成
        bill.setState(Constant.Bill.STATE_BILL_REFUND.getValue());
        bill.setBuyWay("用户订单退款");

        //撤销用户积分
        bill.setId(billId);
        Integer credit = billService.selectByBillId(billId).getCredit();
        Bill bill_credit = bill;
        User user = new User();
        user.setId(uid);
        bill_credit.setCredit(credit);
        creditService.updateUserCredit(bill,user);

        Integer num = billService.updateByBillId(bill);
        map.put("msg", "受影响的行数 " + num.toString());
        return JSON.toJSONString(map);
    }













/***********************************************************************管理员功能*****************************************************************/


    /**
     * 管理员功能1：修改订单信息
     * 允许管理员修改：insuredId petId price credit等
     * @param req
     * @return 更新成功行数
     * @throws InvocationTargetException
     * @throws IllegalAccessException
     */
    @RequestMapping("/updateByAdmin")
    @ResponseBody
    public String updateByAdmin(HttpServletRequest req) throws InvocationTargetException, IllegalAccessException { //状态 购买人id 被保人id 宠物id 两个日期
        Bill bill = new Bill();
        Map<String, String> map = new HashMap<>();
        BeanUtils.populate(bill, req.getParameterMap());
        Person insurer = new Person();
        Pet pet = new Pet();

        //订单未支付时可以修改
        if (billService.selectByBillId(Integer.parseInt(req.getParameter("id"))).getState().equals(Constant.Bill.STATE_BILL_UNPAID.getValue())) {
            if (req.getParameter("insuredId") != null) {
                insurer.setId(Integer.parseInt(req.getParameter("insuredId")));
                bill.setInsured(insurer);
            } else {
                map.put("msg", "被保险人id不允许为空");
            }
            if (req.getParameter("petId") != null) {
                pet.setId(Integer.parseInt(req.getParameter("petId")));
                bill.setPet(pet);
            } else {
                map.put("msg", "被保险宠物不允许为空");
            }
            //日期格式转换
            ConvertUtils.register(new org.apache.commons.beanutils.Converter() {
                @Override
                public Object convert(Class type, Object value) {
                    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
                    try {
                        return simpleDateFormat.parse(value.toString());
                    } catch (ParseException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    return null;
                }
            }, Date.class);
            BeanUtils.setProperty(bill, "useDate", req.getParameter("use_date"));
            BeanUtils.setProperty(bill, "expireDate", req.getParameter("expire_date"));
            Integer num = billService.updateByBillId(bill);
            map.put("msg", "订单修改成功");
        }else{
            map.put("msg", "订单已完成,无法修改信息");
        }
        return JSON.toJSONString(map);
    }

    /**
     * 管理员功能2：查找订单
     * 条件为用户id,订单状态,订单类型,起始日期
     * @param req
     * @return
     * @RequestParam Integer uid, @RequestParam String billState, @RequestParam String billType, @RequestParam String beginDate, @RequestParam String endDate
     */
    @RequestMapping("/searchByAdmin")
    @ResponseBody
    public String searchByAdmin(HttpServletRequest req) {
        Map<String,List> map = new HashMap<>();
        List object;
        User user = new User();
        user.setId( Integer.parseInt(req.getParameter("uid")));
//        if(req.getParameter("billState") == null){
//            System.out.print("参数为空\n");
//        }
        object = billService.selectByUser(user,req.getParameter("billState"),req.getParameter("billType"), req.getParameter("beginDate"), req.getParameter("endDate"));
        map.put("bills", object);
//        Gson gson = new Gson();
//        return gson.toJson(map);
        return JSON.toJSONString(map);
    }


}
